home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Edition 10 / FreelogHS10.iso / Buzz / Buzz_Advanced_Pack.exe / {app} / Dev / elenzil_modulator.cpp < prev    next >
C/C++ Source or Header  |  2001-08-27  |  17KB  |  816 lines

  1. /*
  2.  
  3.   The Elenzil Amplitude Modulator    1.0
  4.  
  5.   20010303 Santa Cruz California
  6.  
  7.   This machine was written primarily because Goenik's Amplitude Modulator
  8.   introduces small but noticable artifacts in the sound.  For instance,
  9.   try tunning the M4 in the included demo song thru a single Goenik's
  10.   and compare to a single Elenzil. You may need to listen with headphones.
  11.  
  12.   Since i used the AM far more than any other single effect,
  13.   i finally got tired of fixing the artifacts up in cooledit,
  14.   and went to write my own.
  15.  
  16.   My guess at the cause of goenik's artifacts is that he calculated
  17.   the stereo spread only once per Work() routine, rather than for each Sample.
  18.   My version does it for each sample. This is probably overkill, but it works for me.
  19.   
  20.  
  21.   !!!
  22.   This machine is Crap for Efficiency.
  23.   I don't really care, as i usually have fast computers.
  24.   --> I am using actual Sin() calls, not lookup tables!
  25.   There is no justification for this except my own laziness.
  26.  
  27.   Also, i built this off of an example from the standard buzz dist,
  28.   and havn't cleaned anything up.
  29.  
  30.   If you fix it up, god bless you.
  31.  
  32.   Okay,
  33.   that's about it.
  34.   Compiled w/ VC6.
  35.  
  36.   Orion Elenzil
  37.   www.elenzil.com
  38.  
  39.  
  40.   */
  41.  
  42.  
  43.  
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include <stdlib.h>
  47. #include <assert.h>
  48. #include <math.h>
  49. #include "../MachineInterface.h"
  50. #include "../dsplib/dsplib.h"
  51. #include <time.h>
  52.  
  53. double const SilentEnough = log(1.0 / 32768);
  54.  
  55. #define MAX_TAPS        1
  56.  
  57. CMachineParameter const paraSpeed = 
  58.     pt_word,                                        // type
  59.     "Speed",
  60.     "Oscillation Speed",                            // description
  61.     0,                                                // MinValue    
  62.     65534,                                            // MaxValue
  63.     65535,                                            // NoValue
  64.     MPF_STATE,                                        // Flags
  65.     1000                                            // Default
  66. };
  67.  
  68. #define UNIT_MHZ    0
  69. #define UNIT_MS        1
  70. #define UNIT_TICK    2
  71. #define UNIT_256    3
  72.  
  73.  
  74. CMachineParameter const paraUnit =
  75.     pt_byte,                                         // type
  76.     "Speed Unit",
  77.     "Speed unit (0 = mHz, 1 = ms, 2 = tick, 3 = 256th of tick)",        
  78.     0,                                                // MinValue    
  79.     3,                                                // MaxValue
  80.     0xff,                                            // NoValue
  81.     MPF_STATE,                                        // Flags
  82.     UNIT_MHZ                                        // Default
  83. };
  84.  
  85. #define    WAVE_SIN        0
  86. #define    WAVE_SQUARE        1
  87. #define    WAVE_TRIANGLE    2
  88. #define    WAVE_SAW        3
  89. #define    WAVE_INVSAW        4
  90. #define    WAVE_CRAZY        5
  91.  
  92.  
  93. CMachineParameter const paraWave =
  94.     pt_byte,                                         // type
  95.     "Wave Type",
  96.     "Wave Type (0 = sin, 1 = square, 2 = triangle 3 = saw, 4 = inv. saw)",
  97.     0,                                                // MinValue    
  98.     4,                                                // MaxValue
  99.     0xff,                                            // NoValue
  100.     MPF_STATE,                                        // Flags
  101.     WAVE_SIN,                                        // Default
  102. };
  103.  
  104. CMachineParameter const paraWavePow =
  105.     pt_byte,                                         // type
  106.     "Wave Power",
  107.     "Wave Power (1 = 1, 2 = ^2, 3 = ^3 etc)",
  108.     1,                                                // MinValue    
  109.     13,                                                // MaxValue
  110.     0xff,                                            // NoValue
  111.     MPF_STATE,                                        // Flags
  112.     1,                                                // Default
  113. };
  114.  
  115. CMachineParameter const paraFloor =
  116.     pt_byte,                                         // type
  117.     "Floor",
  118.     "Floor 00 - fe",
  119.     0,                                                // MinValue    
  120.     0xfe,                                            // MaxValue
  121.     0xff,                                            // NoValue
  122.     MPF_STATE,                                        // Flags
  123.     0                                                // Default
  124. };
  125.  
  126. CMachineParameter const paraSpread =
  127.     pt_word,                                         // type
  128.     "Phase",
  129.     "Phase x0000 - x0800",
  130.     0x0000,                                            // MinValue    
  131.     0x0800,                                            // MaxValue
  132.     0xffff,                                            // NoValue
  133.     MPF_STATE,                                        // Flags
  134.     0x0800,                                            // Default
  135. };
  136.  
  137. CMachineParameter const paraSlur =
  138.     pt_byte,                                         // type
  139.     "Slur",
  140.     "Slur x00 - xfe",
  141.     0x00,                                            // MinValue    
  142.     0xfe,                                            // MaxValue
  143.     0xff,                                            // NoValue
  144.     MPF_STATE,                                        // Flags
  145.     0xf2,                                            // Default
  146. };
  147.  
  148. CMachineParameter const paraGain =
  149.     pt_byte,                                         // type
  150.     "Gain",
  151.     "Gain x00 - xfe",
  152.     0x00,                                            // MinValue    
  153.     0xf0,                                            // MaxValue
  154.     0xff,                                            // NoValue
  155.     MPF_STATE,                                        // Flags
  156.     0x12,                                            // Default
  157. };
  158.  
  159. CMachineParameter const paraReset =
  160.     pt_switch,                                         // type
  161.     "Reset",
  162.     "Reset 1 = Restart Oscillator",
  163.     0x01,                                            // MinValue    
  164.     0x01,                                            // MaxValue
  165.     0xff,                                            // NoValue
  166.     MPF_TICK_ON_EDIT,                                // Flags
  167.     0xff,                                            // Default
  168. };
  169.  
  170. CMachineParameter const *pParameters[] = 
  171.     ¶Speed,
  172.     ¶Unit,
  173.     ¶Wave,
  174.     ¶WavePow,
  175.     ¶Floor,
  176.     ¶Spread,
  177.     ¶Slur,
  178.     ¶Gain,
  179.     ¶Reset,
  180. };
  181.  
  182. #pragma pack(1)
  183.  
  184. class tvals
  185. {
  186. public:
  187.     word    speed;
  188.     byte    unit;
  189.     byte    wave;
  190.     byte    wavepow;
  191.     byte    floor;
  192.     word    spread;
  193.     byte    slur;
  194.     byte    gain;
  195.     byte    reset;
  196. };
  197.  
  198.  
  199. #pragma pack()
  200.  
  201. CMachineInfo const MacInfo = 
  202. {
  203.     MT_EFFECT,                                // type
  204.     MI_VERSION,
  205.     MIF_MONO_TO_STEREO,                        // flags
  206.     1,                                        // min tracks
  207.     1,                                        // max tracks
  208.     0,                                        // numGlobalParameters
  209.     9,                                        // numTrackParameters
  210.     pParameters,
  211.     0,
  212.     NULL,
  213. #ifdef _DEBUG
  214.     "Elenzil Amplitude Modulator (Debug)",    // name
  215. #else
  216.     "Elenzil Amplitude Modulator",
  217. #endif
  218.     "Modulator",                            // short name
  219.     "www.elenzil.com",                        // author
  220.     NULL
  221. };
  222.  
  223. class CTrack
  224. {
  225.     public:
  226.     double    Speed;
  227.     int        Unit;
  228.     int        Wave;
  229.     int        WavePow;
  230.     int        Floor;
  231.     double    Spread;
  232.     double    Slur;
  233.     double    Gain;
  234.     bool    Reset;
  235.  
  236.     double    GetFrequency(CMasterInfo* pMasterInfo);
  237. };
  238.  
  239.  
  240. // Return frequency in seconds.
  241. inline    double    CTrack::GetFrequency(CMasterInfo* pMasterInfo)
  242.     {
  243.     switch (Unit)
  244.         {
  245.         default:
  246.         case    UNIT_MHZ:
  247.             return Speed * 0.001;
  248.             break;
  249.         case    UNIT_MS:
  250.             if (Speed != 0.0)
  251.                 return 1000.0 / Speed;
  252.             else
  253.                 return 1000.0 / 0.5;
  254.             break;
  255.         case    UNIT_TICK:
  256.             if (Speed != 0.0)
  257.                 return pMasterInfo -> TicksPerSec / Speed;
  258.             else
  259.                 return pMasterInfo -> TicksPerSec;
  260.             break;
  261.         case    UNIT_256:
  262.             if (Speed != 0.0)
  263.                 return 256.0 * pMasterInfo -> TicksPerSec / Speed;
  264.             else
  265.                 return 256.0 * pMasterInfo -> TicksPerSec;
  266.             break;
  267.         }
  268.     }
  269.  
  270. class mi : public CMachineInterface
  271. {
  272. public:
  273.     mi();
  274.     virtual ~mi();
  275.  
  276.     virtual void Init(CMachineDataInput * const pi);
  277.     virtual void Tick();
  278. //    virtual bool Work(float *psamples, int numsamples, int const mode);
  279.     virtual bool WorkMonoToStereo(float *pin, float *pout, int numsamples, int const mode);
  280.  
  281.     virtual void SetNumTracks(int const n);
  282.  
  283.     virtual void AttributesChanged();
  284.  
  285.     virtual char const *DescribeValue(int const param, int const value);
  286.  
  287. private:
  288.     void    InitTrack(int const i);
  289.     void    ResetTrack(int const i);
  290.  
  291.     void    TickTrack(CTrack *pt, tvals *ptval);
  292.     void    WorkTrack(CTrack *pt, float *pin, float *pout, int numsamples, int const mode);
  293.     int        MSToSamples(double const ms);
  294.  
  295. private:
  296.     int        IdleCount;    // in samples
  297.     bool    IdleMode;
  298.     int        pos;
  299.     int        pos2;
  300.  
  301.     long    m_Tick;
  302.     double    m_Second;
  303.     double    m_PrevF1;
  304.     double    m_PrevF2;
  305.  
  306. private:
  307.     int numTracks;
  308.     CTrack Tracks[MAX_TAPS];
  309.  
  310.     tvals tval[MAX_TAPS];
  311.  
  312.  
  313. };
  314.  
  315. DLL_EXPORTS
  316.  
  317. mi::mi()
  318. {
  319.     GlobalVals    = NULL;
  320.     TrackVals    = tval;
  321.     AttrVals    = NULL;
  322. }
  323.  
  324. mi::~mi()
  325. {
  326. }
  327.  
  328. char*    CommaPrint(char* txt, int const value)
  329.     {
  330.     char    tmp[32];
  331.     int        i, inum;
  332.     int        j, k;
  333.     sprintf(tmp, "%d", value);
  334.     inum    =    strlen(tmp);
  335.     j        =    inum    % 3;
  336.     k        =    0;
  337.     for (i = 0; i < inum; i++)
  338.         {
  339.         txt[k++] = tmp[i];
  340.         j--;
  341.         if (j == 0 && i < inum - 1)
  342.             {
  343.             txt[k++] = ',';
  344.             j = 3;
  345.             }
  346.         }
  347.     txt[k] = 0;
  348.  
  349.     return txt;
  350.     }
  351.  
  352. char const *mi::DescribeValue(int const param, int const value)
  353. {
  354.     static char txt[16];
  355.     char    tmp[9];
  356.     int        val;
  357.  
  358.     val    =    value;
  359.  
  360.     switch(param)
  361.     {
  362.     case 0:        // freq
  363.         switch(Tracks[0].Unit)
  364.             {
  365.             default:
  366.             case    UNIT_MS:
  367.             case    UNIT_MHZ:
  368.                 CommaPrint(txt, val);
  369.                 sprintf(tmp, " (%.4x)", val);
  370.                 strcat(txt, tmp);
  371.                 break;
  372.             }
  373.         break;
  374.     case 1:        // unit
  375.         switch(val)
  376.             {
  377.             case 0: return "mHz (00)";
  378.             case 1: return "ms (01)";
  379.             case 2: return "tick (02)";
  380.             case 3: return "tick/256 (03)";
  381.             }
  382.         break;
  383.     case 2:        // wave
  384.         char*    s;
  385.         switch(val)
  386.             {
  387.             case WAVE_SIN        : s = "sin"            ; break;
  388.             case WAVE_SQUARE    : s = "square"        ; break;
  389.             case WAVE_TRIANGLE    : s = "triangle"    ; break;
  390.             case WAVE_SAW        : s = "saw"            ; break;
  391.             case WAVE_INVSAW    : s = "inv. saw"    ; break;
  392.             case WAVE_CRAZY        : s = "crazy"        ; break;
  393.             }
  394.             sprintf(txt, "%s (%.2x)", s, val);
  395.         break;
  396.     case 3:        // wave power
  397.         sprintf(txt, "^%d", val);
  398.         break;
  399.     case 4:        // floor
  400.         sprintf(txt, "%d%c (%.2x)", val * 100 / paraFloor.MaxValue, '%', val);
  401.         break;
  402.     case 5:        // spread
  403.         sprintf(txt, "%.3f (%.4x)", (double)val / (double)paraSpread.MaxValue * 2.0 - 1.0, val);
  404.         break;
  405.     case 6:        // slur
  406.         sprintf(txt, "%.3f (%.2x)", (double)val / (double)paraSlur.MaxValue, val);
  407.         break;
  408.     case 7:        // gain
  409.         sprintf(txt, "%.2f (%.2x)", (double)val / (double)paraGain.DefValue, val);
  410.         break;
  411.     case 8:        // reset
  412.         sprintf(txt, "1 = reset oscillation");
  413.         break;
  414.     default:
  415.         return NULL;
  416.     }
  417.  
  418.     return txt;
  419. }
  420.  
  421.  
  422.  
  423. void mi::Init(CMachineDataInput * const pi)
  424. {
  425.     numTracks = 1;
  426.  
  427.     for (int c = 0; c < MAX_TAPS; c++)
  428.     {
  429.         Tracks[c].Speed        = 1000.0;
  430.         Tracks[c].Unit        = UNIT_MHZ;
  431.         Tracks[c].Wave        = WAVE_SIN;
  432.         Tracks[c].WavePow    = 1;
  433.         Tracks[c].Floor        = 0;
  434.         Tracks[c].Spread    = 1.0;
  435.         Tracks[c].Slur        = 0.94;
  436.         Tracks[c].Gain        = 1.0;
  437.         Tracks[c].Reset        = false;
  438.     }
  439.  
  440.     IdleMode    =    true;
  441.     IdleCount    =    0;
  442.     pos            =    0;
  443.     pos2        =    0;
  444.     
  445.     m_Tick        =    0;
  446.     m_Second    =    0.0;
  447.  
  448.     m_PrevF1    =    1.0;
  449.     m_PrevF2    =    1.0;
  450. }
  451.  
  452. void mi::AttributesChanged()
  453. {
  454.     for (int c = 0; c < numTracks; c++)
  455.         InitTrack(c);
  456. }
  457.  
  458.  
  459. void mi::SetNumTracks(int const n)
  460. {
  461.     if (numTracks < n)
  462.     {
  463.         for (int c = numTracks; c < n; c++)
  464.             InitTrack(c);
  465.     }
  466.     else if (n < numTracks)
  467.     {
  468.         for (int c = n; c < numTracks; c++)
  469.             ResetTrack(c);
  470.     
  471.     }
  472.     numTracks = n;
  473. }
  474.  
  475. int mi::MSToSamples(double const ms)
  476. {
  477.     return (int)(pMasterInfo->SamplesPerSec * ms * (1.0 / 1000.0));
  478. }
  479.  
  480. void mi::InitTrack(int const i)
  481. {
  482. }
  483.  
  484. void mi::ResetTrack(int const i)
  485. {
  486. }
  487.  
  488.  
  489. void mi::TickTrack(CTrack *pt, tvals *ptval)
  490. {
  491.     if (ptval->speed    !=    paraSpeed    .NoValue)
  492.         pt->Speed        =    (double)ptval -> speed;
  493.  
  494.     if (ptval->unit        !=    paraUnit    .NoValue)
  495.         pt->Unit        =            ptval -> unit;
  496.  
  497.     if (ptval->wave        !=    paraWave    .NoValue)
  498.         pt->Wave        =            ptval -> wave;
  499.  
  500.     if (ptval->wavepow    !=    paraWavePow    .NoValue)
  501.         pt->WavePow        =            ptval -> wavepow;
  502.  
  503.     if (ptval->floor    !=    paraFloor    .NoValue)
  504.         pt->Floor        =            ptval -> floor;
  505.  
  506.     if (ptval->spread    !=    paraSpread    .NoValue)
  507.         pt->Spread        =    (double)ptval -> spread    / (double)paraSpread.MaxValue * 2.0 - 1.0;
  508.  
  509.     if (ptval->slur        !=    paraSlur    .NoValue)
  510.         pt->Slur        =    (double)ptval -> slur    / (double)paraSlur.MaxValue;
  511.  
  512.     if (ptval->gain        !=    paraGain    .NoValue)
  513.         pt->Gain        =    (double)ptval -> gain    / (double)paraGain.DefValue;
  514.  
  515.     if (ptval->reset    !=    paraReset    .NoValue)
  516.         pt->Reset        =    (bool)    ptval -> reset;
  517. }
  518.  
  519. void mi::Tick()
  520. {
  521.     m_Tick++;
  522.  
  523.     for (int c = 0; c < numTracks; c++)
  524.         TickTrack(Tracks + c, tval+c);
  525. }
  526.  
  527.  
  528.  
  529. bool mi::WorkMonoToStereo(float *pin, float *pout, int numsamples, int const mode)
  530. {
  531.     if (mode != WM_READWRITE)
  532.         return false;
  533.  
  534.     int    i, inum;
  535.     int    j;
  536.     int    p, pnum;
  537.  
  538.     inum    =    numsamples;
  539.     j        =    0;
  540.  
  541.     int        op;
  542.     op        =    pos;
  543.     pos        +=    pMasterInfo ->    PosInTick - pos2;
  544.     pos2    =    pMasterInfo ->    PosInTick;
  545.  
  546.     double    f1;
  547.     double    f2;
  548.     double    SecondsPerSample;
  549.     double    floor;
  550.     double    one_minus_floor;
  551.     double    Spread;
  552.     double    Slur, OneMinusSlur;
  553.     double    Gain;
  554.  
  555.     floor                =    (double)(Tracks[0].Floor) / (double)paraFloor.MaxValue;
  556.     one_minus_floor        =    1.0 - floor;
  557.  
  558.     SecondsPerSample    =    1.0 / (double)pMasterInfo -> SamplesPerSec;
  559.     SecondsPerSample    *=    Tracks[0].GetFrequency(pMasterInfo);
  560.  
  561.     Spread                =    Tracks[0].Spread;
  562.  
  563.     pnum                =    Tracks[0].WavePow;
  564.  
  565.     Slur                =    Tracks[0].Slur;
  566.     OneMinusSlur        =    1.0 - Slur;
  567.  
  568.     Gain                =    Tracks[0].Gain;
  569.  
  570.     if (Tracks[0].Reset)
  571.         {
  572.         m_Second        =    0;
  573.         Tracks[0].Reset    =    false;
  574.         }
  575.  
  576.  
  577.     switch (Tracks[0].Wave)
  578.         {
  579.         default:
  580.         case    WAVE_SIN:
  581.             Spread            *=    PI * 0.5;
  582.             for (i = 0; i < inum; i++)
  583.                 {
  584.                 f1            =    sin(m_Second * PI * 2.0 - Spread) * 0.5 + 0.5;
  585.                 f2            =    sin(m_Second * PI * 2.0 + Spread) * 0.5 + 0.5;
  586.                 m_Second    +=    SecondsPerSample;
  587.                 // This prevents the math from overflowing.
  588.                 if (m_Second > 1.0)
  589.                     m_Second -= 1.0;
  590.  
  591.                 for (p = 1; p < pnum; p++)
  592.                     {
  593.                     f1        *=    f1;
  594.                     f2        *=    f2;
  595.                     }
  596.  
  597.                 f1            =    f1 * one_minus_floor + floor;
  598.                 f2            =    f2 * one_minus_floor + floor;
  599.  
  600.                 f1            *=    Gain;
  601.                 f2            *=    Gain;
  602.  
  603.                 f1            =    OneMinusSlur * f1 + Slur * m_PrevF1;
  604.                 f2            =    OneMinusSlur * f2 + Slur * m_PrevF2;
  605.                 m_PrevF1    =    f1;
  606.                 m_PrevF2    =    f2;
  607.  
  608.                 pout[j]        =    pin[i] * (float)f1;
  609.                 j++;
  610.                 pout[j]        =    pin[i] * (float)f2;
  611.                 j++;
  612.                 }
  613.             break;
  614.  
  615.         case    WAVE_SQUARE:
  616.             Spread            *=    0.25;
  617.             for (i = 0; i < inum; i++)
  618.                 {
  619.                 f1            =    m_Second - Spread + 0.25;
  620.                 if (f1 < 0.0)
  621.                     f1 += 1.0;
  622.                 else if (f1 > 1.0)
  623.                     f1 -= 1.0;
  624.                 f2            =    m_Second + Spread + 0.25;
  625.                 if (f2 < 0.0)
  626.                     f2 += 1.0;
  627.                 else if (f2 > 1.0)
  628.                     f2 -= 1.0;
  629.                 if (f1 < 0.5)
  630.                     f1    =    0.0;
  631.                 else
  632.                     f1    =    1.0;
  633.                 if (f2 < 0.5)
  634.                     f2    =    0.0;
  635.                 else
  636.                     f2    =    1.0;
  637.  
  638.                 m_Second    +=    SecondsPerSample;
  639.                 // This prevents the math from overflowing.
  640.                 if (m_Second > 1.0)
  641.                     m_Second -= 1.0;
  642.  
  643.                 f1            =    f1 * one_minus_floor + floor;
  644.                 f2            =    f2 * one_minus_floor + floor;
  645.  
  646.                 f1            *=    Gain;
  647.                 f2            *=    Gain;
  648.  
  649.                 f1            =    OneMinusSlur * f1 + Slur * m_PrevF1;
  650.                 f2            =    OneMinusSlur * f2 + Slur * m_PrevF2;
  651.                 m_PrevF1    =    f1;
  652.                 m_PrevF2    =    f2;
  653.  
  654.                 pout[j]        =    pin[i] * (float)f1;
  655.                 j++;
  656.                 pout[j]        =    pin[i] * (float)f2;
  657.                 j++;
  658.                 }
  659.             break;
  660.  
  661.         case    WAVE_TRIANGLE:
  662.             Spread            *=    0.25;
  663.             for (i = 0; i < inum; i++)
  664.                 {
  665.                 f1            =    m_Second - Spread + 0.25;
  666.                 if (f1 < 0.0)
  667.                     f1 += 1.0;
  668.                 else if (f1 > 1.0)
  669.                     f1 -= 1.0;
  670.                 f2            =    m_Second + Spread + 0.25;
  671.                 if (f2 < 0.0)
  672.                     f2 += 1.0;
  673.                 else if (f2 > 1.0)
  674.                     f2 -= 1.0;
  675.  
  676.                 f1    *=    2.0;
  677.                 f2    *=    2.0;
  678.  
  679.                 if (f1 > 1.0)
  680.                     f1    =    2.0 - f1;
  681.                 if (f2 > 1.0)
  682.                     f2    =    2.0 - f2;
  683.  
  684.                 m_Second    +=    SecondsPerSample;
  685.                 // This prevents the math from overflowing.
  686.                 if (m_Second > 1.0)
  687.                     m_Second -= 1.0;
  688.  
  689.                 for (p = 1; p < pnum; p++)
  690.                     {
  691.                     f1        *=    f1;
  692.                     f2        *=    f2;
  693.                     }
  694.  
  695.                 f1            =    f1 * one_minus_floor + floor;
  696.                 f2            =    f2 * one_minus_floor + floor;
  697.  
  698.                 f1            *=    Gain;
  699.                 f2            *=    Gain;
  700.  
  701.                 f1            =    OneMinusSlur * f1 + Slur * m_PrevF1;
  702.                 f2            =    OneMinusSlur * f2 + Slur * m_PrevF2;
  703.                 m_PrevF1    =    f1;
  704.                 m_PrevF2    =    f2;
  705.  
  706.                 pout[j]        =    pin[i] * (float)f1;
  707.                 j++;
  708.                 pout[j]        =    pin[i] * (float)f2;
  709.                 j++;
  710.                 }
  711.             break;
  712.  
  713.         case    WAVE_SAW:
  714.             Spread            *=    0.25;
  715.             for (i = 0; i < inum; i++)
  716.                 {
  717.                 f1            =    m_Second - Spread + 0.25;
  718.                 if (f1 < 0.0)
  719.                     f1 += 1.0;
  720.                 else if (f1 > 1.0)
  721.                     f1 -= 1.0;
  722.                 f2            =    m_Second + Spread + 0.25;
  723.                 if (f2 < 0.0)
  724.                     f2 += 1.0;
  725.                 else if (f2 > 1.0)
  726.                     f2 -= 1.0;
  727.  
  728.                 m_Second    +=    SecondsPerSample;
  729.                 // This prevents the math from overflowing.
  730.                 if (m_Second > 1.0)
  731.                     m_Second -= 1.0;
  732.  
  733.                 for (p = 1; p < pnum; p++)
  734.                     {
  735.                     f1        *=    f1;
  736.                     f2        *=    f2;
  737.                     }
  738.  
  739.                 f1            =    f1 * one_minus_floor + floor;
  740.                 f2            =    f2 * one_minus_floor + floor;
  741.  
  742.                 f1            *=    Gain;
  743.                 f2            *=    Gain;
  744.  
  745.                 f1            =    OneMinusSlur * f1 + Slur * m_PrevF1;
  746.                 f2            =    OneMinusSlur * f2 + Slur * m_PrevF2;
  747.                 m_PrevF1    =    f1;
  748.                 m_PrevF2    =    f2;
  749.  
  750.                 pout[j]        =    pin[i] * (float)f1;
  751.                 j++;
  752.                 pout[j]        =    pin[i] * (float)f2;
  753.                 j++;
  754.                 }
  755.             break;
  756.         case    WAVE_INVSAW:
  757.             Spread            *=    0.25;
  758.             for (i = 0; i < inum; i++)
  759.                 {
  760.                 f1            =    m_Second - Spread + 0.25;
  761.                 if (f1 < 0.0)
  762.                     f1 += 1.0;
  763.                 else if (f1 > 1.0)
  764.                     f1 -= 1.0;
  765.                 f2            =    m_Second + Spread + 0.25;
  766.                 if (f2 < 0.0)
  767.                     f2 += 1.0;
  768.                 else if (f2 > 1.0)
  769.                     f2 -= 1.0;
  770.  
  771.                 f1    =    1.0 - f1;
  772.                 f2    =    1.0 - f2;
  773.  
  774.                 m_Second    +=    SecondsPerSample;
  775.                 // This prevents the math from overflowing.
  776.                 if (m_Second > 1.0)
  777.                     m_Second -= 1.0;
  778.  
  779.                 for (p = 1; p < pnum; p++)
  780.                     {
  781.                     f1        *=    f1;
  782.                     f2        *=    f2;
  783.                     }
  784.  
  785.                 f1            =    f1 * one_minus_floor + floor;
  786.                 f2            =    f2 * one_minus_floor + floor;
  787.  
  788.                 f1            *=    Gain;
  789.                 f2            *=    Gain;
  790.  
  791.                 f1            =    OneMinusSlur * f1 + Slur * m_PrevF1;
  792.                 f2            =    OneMinusSlur * f2 + Slur * m_PrevF2;
  793.                 m_PrevF1    =    f1;
  794.                 m_PrevF2    =    f2;
  795.  
  796.                 pout[j]        =    pin[i] * (float)f1;
  797.                 j++;
  798.                 pout[j]        =    pin[i] * (float)f2;
  799.                 j++;
  800.                 }
  801.             break;
  802.         }
  803.  
  804.     return true;
  805. }
  806.